/*
 * BLUE2View.java
 */

package blue2;

import DetectarLineas.*;
import RestaurarImagen.Paso1_BSR;
import RestaurarImagen.Paso2_BSR;
import java.awt.Image;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jdesktop.application.Action;
import org.jdesktop.application.ResourceMap;
import org.jdesktop.application.SingleFrameApplication;
import org.jdesktop.application.FrameView;
import org.jdesktop.application.TaskMonitor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.Timer;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;

/**
 * The application's main frame.
 */
public class BLUE2View extends FrameView {

    BufferedImage bimg_anterior, bimg_actual, bimg_original, mascara_BSD;

    public BLUE2View(SingleFrameApplication app) {
        super(app);

        initComponents();

        Texto.setText("La aplicación de Restauración de imagenes" +
                    "\ncon rayones azules está lista para ser usada." +
                    "\nPuede proceder a abrir la imagen deseada en" +
                    "\nArchivo/Abrir o pulsando Ctrl+a.");

        TextoEstado.setText("Listo");

        BSD.setEnabled(false);
        BSR.setEnabled(false);
        Paso11.setEnabled(false);
        Paso12.setEnabled(false);
        Paso13.setEnabled(false);
        Paso14.setEnabled(false);
        Paso21.setEnabled(false);
        Paso22.setEnabled(false);
        TODO.setEnabled(false);
        
        // status bar initialization - message timeout, idle icon and busy animation, etc
        ResourceMap resourceMap = getResourceMap();
        int messageTimeout = resourceMap.getInteger("StatusBar.messageTimeout");
        messageTimer = new Timer(messageTimeout, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                TextoEstado.setText("");
            }
        });
        messageTimer.setRepeats(false);
        int busyAnimationRate = resourceMap.getInteger("StatusBar.busyAnimationRate");
        for (int i = 0; i < busyIcons.length; i++) {
            busyIcons[i] = resourceMap.getIcon("StatusBar.busyIcons[" + i + "]");
        }
        busyIconTimer = new Timer(busyAnimationRate, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                busyIconIndex = (busyIconIndex + 1) % busyIcons.length;
                statusAnimationLabel.setIcon(busyIcons[busyIconIndex]);
            }
        });
        idleIcon = resourceMap.getIcon("StatusBar.idleIcon");
        statusAnimationLabel.setIcon(idleIcon);
        BarraProceso.setVisible(false);

        // connecting action tasks to status bar via TaskMonitor
        TaskMonitor taskMonitor = new TaskMonitor(getApplication().getContext());
        taskMonitor.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                String propertyName = evt.getPropertyName();
                if ("started".equals(propertyName)) {
                    if (!busyIconTimer.isRunning()) {
                        statusAnimationLabel.setIcon(busyIcons[0]);
                        busyIconIndex = 0;
                        busyIconTimer.start();
                    }
                    BarraProceso.setVisible(true);
                    BarraProceso.setIndeterminate(true);
                } else if ("done".equals(propertyName)) {
                    busyIconTimer.stop();
                    statusAnimationLabel.setIcon(idleIcon);
                    BarraProceso.setVisible(false);
                    BarraProceso.setValue(0);
                } else if ("message".equals(propertyName)) {
                    String text = (String)(evt.getNewValue());
                    TextoEstado.setText((text == null) ? "" : text);
                    messageTimer.restart();
                } else if ("progress".equals(propertyName)) {
                    int value = (Integer)(evt.getNewValue());
                    BarraProceso.setVisible(true);
                    BarraProceso.setIndeterminate(false);
                    BarraProceso.setValue(value);
                }
            }
        });
    }

    @Action
    public void showAboutBox() {
        if (aboutBox == null) {
            JFrame mainFrame = BLUE2App.getApplication().getMainFrame();
            aboutBox = new BLUE2AboutBox(mainFrame);
            aboutBox.setLocationRelativeTo(mainFrame);
        }
        BLUE2App.getApplication().show(aboutBox);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        mainPanel = new javax.swing.JPanel();
        PBotones = new javax.swing.JPanel();
        BSD = new javax.swing.JButton();
        Paso11 = new javax.swing.JButton();
        Paso12 = new javax.swing.JButton();
        Paso13 = new javax.swing.JButton();
        Paso14 = new javax.swing.JButton();
        BSR = new javax.swing.JButton();
        Paso21 = new javax.swing.JButton();
        Paso22 = new javax.swing.JButton();
        TODO = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        Texto = new javax.swing.JTextArea();
        PAnterior = new javax.swing.JPanel();
        LAnterior = new javax.swing.JLabel();
        PActual = new javax.swing.JPanel();
        LActual = new javax.swing.JLabel();
        menuBar = new javax.swing.JMenuBar();
        javax.swing.JMenu fileMenu = new javax.swing.JMenu();
        openMenuItem = new javax.swing.JMenuItem();
        saveMenuItem = new javax.swing.JMenuItem();
        javax.swing.JMenuItem exitMenuItem = new javax.swing.JMenuItem();
        javax.swing.JMenu helpMenu = new javax.swing.JMenu();
        javax.swing.JMenuItem aboutMenuItem = new javax.swing.JMenuItem();
        statusPanel = new javax.swing.JPanel();
        javax.swing.JSeparator statusPanelSeparator = new javax.swing.JSeparator();
        TextoEstado = new javax.swing.JLabel();
        statusAnimationLabel = new javax.swing.JLabel();
        BarraProceso = new javax.swing.JProgressBar();

        mainPanel.setName("mainPanel"); // NOI18N

        PBotones.setName("PBotones"); // NOI18N

        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(blue2.BLUE2App.class).getContext().getResourceMap(BLUE2View.class);
        BSD.setBackground(resourceMap.getColor("BSD.background")); // NOI18N
        BSD.setForeground(resourceMap.getColor("BSD.foreground")); // NOI18N
        BSD.setText(resourceMap.getString("BSD.text")); // NOI18N
        BSD.setToolTipText(resourceMap.getString("BSD.toolTipText")); // NOI18N
        BSD.setName("BSD"); // NOI18N
        BSD.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                BSDActionPerformed(evt);
            }
        });

        Paso11.setBackground(resourceMap.getColor("Paso11.background")); // NOI18N
        Paso11.setForeground(resourceMap.getColor("Paso11.foreground")); // NOI18N
        Paso11.setText(resourceMap.getString("Paso11.text")); // NOI18N
        Paso11.setToolTipText(resourceMap.getString("Paso11.toolTipText")); // NOI18N
        Paso11.setName("Paso11"); // NOI18N
        Paso11.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Paso11ActionPerformed(evt);
            }
        });

        Paso12.setBackground(resourceMap.getColor("Paso12.background")); // NOI18N
        Paso12.setForeground(resourceMap.getColor("Paso12.foreground")); // NOI18N
        Paso12.setText(resourceMap.getString("Paso12.text")); // NOI18N
        Paso12.setToolTipText(resourceMap.getString("Paso12.toolTipText")); // NOI18N
        Paso12.setName("Paso12"); // NOI18N
        Paso12.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Paso12ActionPerformed(evt);
            }
        });

        Paso13.setBackground(resourceMap.getColor("Paso13.background")); // NOI18N
        Paso13.setForeground(resourceMap.getColor("Paso13.foreground")); // NOI18N
        Paso13.setText(resourceMap.getString("Paso13.text")); // NOI18N
        Paso13.setToolTipText(resourceMap.getString("Paso13.toolTipText")); // NOI18N
        Paso13.setName("Paso13"); // NOI18N
        Paso13.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Paso13ActionPerformed(evt);
            }
        });

        Paso14.setBackground(resourceMap.getColor("Paso14.background")); // NOI18N
        Paso14.setForeground(resourceMap.getColor("Paso14.foreground")); // NOI18N
        Paso14.setText(resourceMap.getString("Paso14.text")); // NOI18N
        Paso14.setToolTipText(resourceMap.getString("Paso14.toolTipText")); // NOI18N
        Paso14.setName("Paso14"); // NOI18N
        Paso14.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Paso14ActionPerformed(evt);
            }
        });

        BSR.setBackground(resourceMap.getColor("Paso22.background")); // NOI18N
        BSR.setForeground(resourceMap.getColor("Paso22.foreground")); // NOI18N
        BSR.setText(resourceMap.getString("BSR.text")); // NOI18N
        BSR.setToolTipText(resourceMap.getString("BSR.toolTipText")); // NOI18N
        BSR.setName("BSR"); // NOI18N
        BSR.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                BSRActionPerformed(evt);
            }
        });

        Paso21.setBackground(resourceMap.getColor("Paso22.background")); // NOI18N
        Paso21.setForeground(resourceMap.getColor("Paso22.foreground")); // NOI18N
        Paso21.setText(resourceMap.getString("Paso21.text")); // NOI18N
        Paso21.setToolTipText(resourceMap.getString("Paso21.toolTipText")); // NOI18N
        Paso21.setName("Paso21"); // NOI18N
        Paso21.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Paso21ActionPerformed(evt);
            }
        });

        Paso22.setBackground(resourceMap.getColor("Paso22.background")); // NOI18N
        Paso22.setForeground(resourceMap.getColor("Paso22.foreground")); // NOI18N
        Paso22.setText(resourceMap.getString("Paso22.text")); // NOI18N
        Paso22.setToolTipText(resourceMap.getString("Paso22.toolTipText")); // NOI18N
        Paso22.setName("Paso22"); // NOI18N
        Paso22.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Paso22ActionPerformed(evt);
            }
        });

        TODO.setBackground(resourceMap.getColor("TODO.background")); // NOI18N
        TODO.setForeground(resourceMap.getColor("TODO.foreground")); // NOI18N
        TODO.setText(resourceMap.getString("TODO.text")); // NOI18N
        TODO.setToolTipText(resourceMap.getString("TODO.toolTipText")); // NOI18N
        TODO.setName("TODO"); // NOI18N
        TODO.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                TODOActionPerformed(evt);
            }
        });

        jScrollPane1.setName("jScrollPane1"); // NOI18N

        Texto.setColumns(20);
        Texto.setFont(resourceMap.getFont("Texto.font")); // NOI18N
        Texto.setRows(5);
        Texto.setText(resourceMap.getString("Texto.text")); // NOI18N
        Texto.setToolTipText(resourceMap.getString("Texto.toolTipText")); // NOI18N
        Texto.setName("Texto"); // NOI18N
        jScrollPane1.setViewportView(Texto);

        javax.swing.GroupLayout PBotonesLayout = new javax.swing.GroupLayout(PBotones);
        PBotones.setLayout(PBotonesLayout);
        PBotonesLayout.setHorizontalGroup(
            PBotonesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, PBotonesLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 265, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(PBotonesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(PBotonesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                        .addComponent(Paso12)
                        .addComponent(Paso11)
                        .addComponent(Paso13)
                        .addComponent(Paso14))
                    .addComponent(BSD))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(PBotonesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(PBotonesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(PBotonesLayout.createSequentialGroup()
                            .addComponent(BSR)
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 10, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addComponent(Paso21, javax.swing.GroupLayout.Alignment.TRAILING)
                        .addComponent(Paso22, javax.swing.GroupLayout.Alignment.TRAILING))
                    .addComponent(TODO))
                .addContainerGap())
        );
        PBotonesLayout.setVerticalGroup(
            PBotonesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, PBotonesLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(PBotonesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(PBotonesLayout.createSequentialGroup()
                        .addGap(11, 11, 11)
                        .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 139, Short.MAX_VALUE))
                    .addGroup(PBotonesLayout.createSequentialGroup()
                        .addGroup(PBotonesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(BSR)
                            .addComponent(BSD))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(PBotonesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(Paso21)
                            .addComponent(Paso11))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(PBotonesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(Paso22)
                            .addComponent(Paso12))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(Paso13)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(PBotonesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(TODO)
                            .addComponent(Paso14))))
                .addContainerGap())
        );

        PAnterior.setName("PAnterior"); // NOI18N

        LAnterior.setText(resourceMap.getString("LAnterior.text")); // NOI18N
        LAnterior.setToolTipText(resourceMap.getString("LAnterior.toolTipText")); // NOI18N
        LAnterior.setName("LAnterior"); // NOI18N

        javax.swing.GroupLayout PAnteriorLayout = new javax.swing.GroupLayout(PAnterior);
        PAnterior.setLayout(PAnteriorLayout);
        PAnteriorLayout.setHorizontalGroup(
            PAnteriorLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(LAnterior, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 413, Short.MAX_VALUE)
        );
        PAnteriorLayout.setVerticalGroup(
            PAnteriorLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(LAnterior, javax.swing.GroupLayout.DEFAULT_SIZE, 387, Short.MAX_VALUE)
        );

        PActual.setName("PActual"); // NOI18N

        LActual.setText(resourceMap.getString("LActual.text")); // NOI18N
        LActual.setToolTipText(resourceMap.getString("LActual.toolTipText")); // NOI18N
        LActual.setName("LActual"); // NOI18N

        javax.swing.GroupLayout PActualLayout = new javax.swing.GroupLayout(PActual);
        PActual.setLayout(PActualLayout);
        PActualLayout.setHorizontalGroup(
            PActualLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(LActual, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 313, Short.MAX_VALUE)
        );
        PActualLayout.setVerticalGroup(
            PActualLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(LActual, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 566, Short.MAX_VALUE)
        );

        javax.swing.GroupLayout mainPanelLayout = new javax.swing.GroupLayout(mainPanel);
        mainPanel.setLayout(mainPanelLayout);
        mainPanelLayout.setHorizontalGroup(
            mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, mainPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(PActual, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(PBotones, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(PAnterior, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );
        mainPanelLayout.setVerticalGroup(
            mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(mainPanelLayout.createSequentialGroup()
                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(mainPanelLayout.createSequentialGroup()
                        .addComponent(PBotones, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18)
                        .addComponent(PAnterior, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                    .addComponent(PActual, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );

        menuBar.setName("menuBar"); // NOI18N

        fileMenu.setText(resourceMap.getString("fileMenu.text")); // NOI18N
        fileMenu.setName("fileMenu"); // NOI18N

        openMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_A, java.awt.event.InputEvent.CTRL_MASK));
        openMenuItem.setText(resourceMap.getString("openMenuItem.text")); // NOI18N
        openMenuItem.setToolTipText(resourceMap.getString("openMenuItem.toolTipText")); // NOI18N
        openMenuItem.setName("openMenuItem"); // NOI18N
        openMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                openMenuItemActionPerformed(evt);
            }
        });
        fileMenu.add(openMenuItem);

        saveMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_G, java.awt.event.InputEvent.CTRL_MASK));
        saveMenuItem.setText(resourceMap.getString("saveMenuItem.text")); // NOI18N
        saveMenuItem.setToolTipText(resourceMap.getString("saveMenuItem.toolTipText")); // NOI18N
        saveMenuItem.setName("saveMenuItem"); // NOI18N
        saveMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveMenuItemActionPerformed(evt);
            }
        });
        fileMenu.add(saveMenuItem);

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(blue2.BLUE2App.class).getContext().getActionMap(BLUE2View.class, this);
        exitMenuItem.setAction(actionMap.get("quit")); // NOI18N
        exitMenuItem.setText(resourceMap.getString("exitMenuItem.text")); // NOI18N
        exitMenuItem.setToolTipText(resourceMap.getString("exitMenuItem.toolTipText")); // NOI18N
        exitMenuItem.setName("exitMenuItem"); // NOI18N
        fileMenu.add(exitMenuItem);

        menuBar.add(fileMenu);

        helpMenu.setText(resourceMap.getString("helpMenu.text")); // NOI18N
        helpMenu.setToolTipText(resourceMap.getString("helpMenu.toolTipText")); // NOI18N
        helpMenu.setName("helpMenu"); // NOI18N

        aboutMenuItem.setAction(actionMap.get("showAboutBox")); // NOI18N
        aboutMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_A, java.awt.event.InputEvent.ALT_MASK));
        aboutMenuItem.setText(resourceMap.getString("aboutMenuItem.text")); // NOI18N
        aboutMenuItem.setToolTipText(resourceMap.getString("aboutMenuItem.toolTipText")); // NOI18N
        aboutMenuItem.setName("aboutMenuItem"); // NOI18N
        helpMenu.add(aboutMenuItem);

        menuBar.add(helpMenu);

        statusPanel.setToolTipText(resourceMap.getString("statusPanel.toolTipText")); // NOI18N
        statusPanel.setName("statusPanel"); // NOI18N

        statusPanelSeparator.setName("statusPanelSeparator"); // NOI18N

        TextoEstado.setName("TextoEstado"); // NOI18N

        statusAnimationLabel.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        statusAnimationLabel.setName("statusAnimationLabel"); // NOI18N

        BarraProceso.setName("BarraProceso"); // NOI18N

        javax.swing.GroupLayout statusPanelLayout = new javax.swing.GroupLayout(statusPanel);
        statusPanel.setLayout(statusPanelLayout);
        statusPanelLayout.setHorizontalGroup(
            statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(statusPanelSeparator, javax.swing.GroupLayout.DEFAULT_SIZE, 752, Short.MAX_VALUE)
            .addGroup(statusPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(TextoEstado)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 582, Short.MAX_VALUE)
                .addComponent(BarraProceso, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(statusAnimationLabel)
                .addContainerGap())
        );
        statusPanelLayout.setVerticalGroup(
            statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(statusPanelLayout.createSequentialGroup()
                .addComponent(statusPanelSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 2, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(TextoEstado)
                    .addComponent(statusAnimationLabel)
                    .addComponent(BarraProceso, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(3, 3, 3))
        );

        setComponent(mainPanel);
        setMenuBar(menuBar);
        setStatusBar(statusPanel);
    }// </editor-fold>//GEN-END:initComponents

    private void openMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openMenuItemActionPerformed
        JFileChooser abrirImagen = new JFileChooser();
        abrirImagen.showOpenDialog(this.getComponent());

        File fichero = abrirImagen.getSelectedFile();
        if(fichero != null){
            try {
                int ancho, alto;
                BufferedImage bimg = ImageIO.read(fichero);
                bimg_original = bimg;
                bimg_actual = bimg;
                Image img1 = ajustarLActual(bimg);
                LActual.setIcon(new ImageIcon(img1));
            } catch (IOException ex) {
                Logger.getLogger(BLUE2View.class.getName()).log(Level.SEVERE, null, ex);
            }
            Texto.setText("La imagen ha sido cargada correctamente." +
                        "\nA continuación puede:" +
                        "\n\tRestaurar la imagen directamente pulsando en TODO." +
                        "\n\tRealizar la detección de rayones pulsando en BSD." +
                        "\n\tRealizar el paso 1 de la detección pulsando en Paso1.");
        }

        BSD.setEnabled(true);
        Paso11.setEnabled(true);
        TODO.setEnabled(true);
        BSR.setEnabled(false);
        Paso12.setEnabled(false);
        Paso13.setEnabled(false);
        Paso14.setEnabled(false);
        Paso21.setEnabled(false);
        Paso22.setEnabled(false);

    }//GEN-LAST:event_openMenuItemActionPerformed

    private void actualizarLAnterior (){
        Image img1 = null;
        if(LAnterior.getWidth() < bimg_anterior.getWidth()){
            img1 = bimg_anterior.getScaledInstance(LAnterior.getWidth(), -1, Image.SCALE_SMOOTH);
            if(LAnterior.getHeight() < img1.getHeight(null))
                img1 = img1.getScaledInstance(-1, LAnterior.getHeight(), Image.SCALE_SMOOTH);
        }else if (bimg_anterior.getHeight() > LAnterior.getHeight())
                img1 = bimg_anterior.getScaledInstance(-1, LAnterior.getHeight(), Image.SCALE_SMOOTH);
        else
            img1 = (Image) bimg_anterior;

        LAnterior.setIcon(new ImageIcon(img1));
    }

    private Image ajustarLActual (BufferedImage bimg){
        Image img1;

        if(bimg.getWidth() > LActual.getWidth()){
            img1 = bimg.getScaledInstance(LActual.getWidth(), -1, Image.SCALE_SMOOTH);
            if(img1.getHeight(null) > LActual.getHeight())
                img1 = bimg.getScaledInstance(-1, LActual.getHeight(), Image.SCALE_SMOOTH);
        }else if(bimg.getHeight() > LActual.getHeight())
                img1 = bimg.getScaledInstance(-1, LActual.getHeight(), Image.SCALE_SMOOTH);
        else
            img1 = (Image) bimg;

        return img1;
    }
    private void Paso11ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Paso11ActionPerformed

        bimg_anterior = bimg_actual;

        //Para la vista anterior lo ajustamos
        actualizarLAnterior ();

        //A la actual le aplicamos los pasos indicados
        Paso1 p1 = new Paso1();
        bimg_actual = p1.aplica_paso1(bimg_actual);

        LActual.setIcon(new ImageIcon(ajustarLActual(bimg_actual)));

        Texto.setText("En este paso se ha realizado un preprocesamiento sobre" +
                    "\nla imagen para la reduccion del ruido conservando" +
                    "\nlas aristas verticales." +
                    "\nConsiste en el filtro de la media 11x1 de cada pixel." +
                    "\nA la izquierda está la imagen resultante y abajo la original." +
                    "\nContinue pulsando Paso2.  ");

        BSD.setEnabled(false);
        Paso11.setEnabled(false);
        Paso12.setEnabled(true);
        TODO.setEnabled(false);
    }//GEN-LAST:event_Paso11ActionPerformed

    private void BSDActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_BSDActionPerformed

        Texto.setText("En este paso se ha realizado la fase de detección de" +
                    "\nrayones azules sobre la imagen. El resultado es" +
                    "\nuna imagen binaria donde los pixeles blancos" +
                    "\nmuestran las zonas de rayones azules." +
                    "\nA la izquierda está la máscara del scratch y abajo la original." +
                    "\nContinue pulsando el botón BSR o Paso1 del BSR para restaurar la imagen.");

        bimg_anterior = bimg_actual;

        actualizarLAnterior ();
       
        //Pasos del algoritmo de detección
        Paso1 p1 = new Paso1();
        Paso2 p2 = new Paso2();
        Paso3 p3 = new Paso3();
        Paso4 p4 = new Paso4();

        //Aplicar los pasos
        bimg_actual = p1.aplica_paso1(bimg_actual);
        bimg_actual = p2.aplica_paso2(bimg_actual);
        bimg_actual = p3.aplica_paso3(bimg_actual);
        bimg_actual = p4.aplica_paso4(bimg_actual);

         mascara_BSD = bimg_actual;
         
        LActual.setIcon(new ImageIcon(ajustarLActual(bimg_actual)));

        BSD.setEnabled(false);
        Paso11.setEnabled(false);
        TODO.setEnabled(false);
        BSR.setEnabled(true);
        Paso21.setEnabled(true);
    }//GEN-LAST:event_BSDActionPerformed

    private void Paso12ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Paso12ActionPerformed
        Texto.setText("En este paso se ha realizado un realce de las líneas" +
                    "\nazules verticales y se eliminan las aristas verticales" +
                    "\nno producidas por líneas azules verticales." +
                    "\nEste paso consiste en filtro paso de alta de una dimensión" +
                    "\naplicado a 3w pixeles vecinos, con w = ancho del rayón azul" +
                    "\nA la izquierda está la máscara del scratch y abajo la imagen anterior." +
                    "\nContinue pulsando el botón Paso3 del BSD para obtener la máscara.");

        bimg_anterior = bimg_actual;

        actualizarLAnterior ();

        Paso2 p2 = new Paso2();
        bimg_actual = p2.aplica_paso2(bimg_actual);
        
        LActual.setIcon(new ImageIcon(ajustarLActual(bimg_actual)));

        Paso12.setEnabled(false);
        Paso13.setEnabled(true);
    }//GEN-LAST:event_Paso12ActionPerformed

    private void Paso13ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Paso13ActionPerformed
         bimg_anterior = bimg_actual;

        actualizarLAnterior ();

        Paso3 p3 = new Paso3();
        bimg_actual = p3.aplica_paso3(bimg_actual);
        
        LActual.setIcon(new ImageIcon(ajustarLActual(bimg_actual)));

        Texto.setText("En este paso se ha realizado una binarización al resultado" +
                    "\nde la fase anterior. Para ello se pasa del espacio" +
                    "\nRGB al espacio HSV. Sobre una imagen en negro, ponemos" +
                    "\nen blanco el pixel si el valor del color corresponde al azul." +
                    "\nA la izquierda está la imagen binarizada y abajo la imagen anterior." +
                    "\nContinue pulsando el botón Paso4 del BSD para obtener la máscara.");

        Paso13.setEnabled(false);
        Paso14.setEnabled(true);
    }//GEN-LAST:event_Paso13ActionPerformed

    private void Paso14ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Paso14ActionPerformed

        bimg_anterior = bimg_actual;

        actualizarLAnterior ();

        Paso4 p4 = new Paso4();

        bimg_actual = p4.aplica_paso4(bimg_actual);
        mascara_BSD = bimg_actual;

        LActual.setIcon(new ImageIcon(ajustarLActual(bimg_actual)));

        Texto.setText("En este paso finaliza la fase de detección de" +
                    "\nrayones azules sobre la imagen. Este paso" +
                    "\nconsiste en un refinamiento de la máscara de rayones." +
                    "\nPara ello detecta líneas verticales sobre casi toda la imagen." +
                    "\nA la izquierda está la máscara del scratch y abajo la imagen anterior." +
                    "\nContinue pulsando el botón BSR o Paso1 del BSR para restaurar la imagen.");

        Paso14.setEnabled(false);
        Paso21.setEnabled(true);
        BSR.setEnabled(true);
    }//GEN-LAST:event_Paso14ActionPerformed

    private void Paso21ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Paso21ActionPerformed
        bimg_anterior = bimg_original;
        actualizarLAnterior ();

        Paso1_BSR p1 = new Paso1_BSR();

        bimg_actual = p1.aplica_paso1(bimg_original);
        LActual.setIcon(new ImageIcon(ajustarLActual(bimg_actual)));

        Texto.setText("En este paso se ha realizado preprocesamiento de la banda" +
                    "\nroja sobre la imagen original. Este consiste en un" +
                    "\nfiltro rank-order, en este caso se ha tomado el" +
                    "\nfiltro de la mediana con una máscara 3x3." +
                    "\nA la izquierda está el resultado y abajo la imagen original." +
                    "\nContinue pulsando el botón Paso2 del BSR para restaurar la imagen.");

        Paso21.setEnabled(false);
        Paso22.setEnabled(true);
        BSR.setEnabled(false);
    }//GEN-LAST:event_Paso21ActionPerformed
/* A median filter is a rank-order filter where the rank is 0.5 -- the 50th percentile.
 Median filters: This rank order filter is interesting because the median is the
most costly single rank that we could wish to obtain.
 */
    private void Paso22ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Paso22ActionPerformed
        bimg_anterior = bimg_actual;
        actualizarLAnterior ();
        
        Paso2_BSR p2 = new Paso2_BSR();

        bimg_actual = p2.aplica_paso2(bimg_actual, mascara_BSD);
        LActual.setIcon(new ImageIcon(ajustarLActual(bimg_actual)));

        Texto.setText("Este paso corresponde al paso 2 y 3 de la especificación." +
                    "\nEste calcula sobre los píxeles vecinos no corruptos del rayón"+
                    "\nel desplazamiento min, max y medio de la banda verde y azul" +
                    "\n sobre la banda roja. Luego añade el desplazamiento medio a" +
                    "\ntodos los píxeles de la banda verde y azul pertenecientes al." +
                    "\nárea del rayón." +
                    "\nA la izquierda está el resultado y abajo la imagen anterior." +
                    "\nFinalizado la restauración de la imagen. Puede proceder a" +
                    "\nguardar la imagen restaurada en Archivo/Guardar");

        Paso22.setEnabled(false);
        BSD.setEnabled(true);
        Paso11.setEnabled(true);
        TODO.setEnabled(true);
    }//GEN-LAST:event_Paso22ActionPerformed

    private void BSRActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_BSRActionPerformed
        bimg_anterior = bimg_actual;
        actualizarLAnterior ();

        Paso1_BSR p1 = new Paso1_BSR();
        Paso2_BSR p2 = new Paso2_BSR();

        bimg_actual = p1.aplica_paso1(bimg_original);
        bimg_actual = p2.aplica_paso2(bimg_actual, mascara_BSD);
        LActual.setIcon(new ImageIcon(ajustarLActual(bimg_actual)));

        Texto.setText("En este paso se ha realizado la fase de eliminación de rayones azules." +
                    "\nEste paso utiliza la máscara de rayones y la imagen original"+
                    "\npara reconstruir la información corrupta de la imagen." +
                    "\nA la izquierda la imagen restaurada y abajo la máscara usada." +
                    "\nFinalizado la restauración de la imagen. Puede proceder a" +
                    "\nguardar la imagen restaurada en Archivo/Guardar.");

        Paso21.setEnabled(false);
        BSR.setEnabled(false);
        BSD.setEnabled(true);
        Paso11.setEnabled(true);
        TODO.setEnabled(true);
    }//GEN-LAST:event_BSRActionPerformed

    private void TODOActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_TODOActionPerformed

        Texto.setText("Se va a realizar la fase de detección de rayones y la fase" +
                    "\nde eliminación de rayones azules para obtener finalmente"+
                    "\nuna imagen restaurada. Si desea más información del proceso" +
                    "\npuede ir paso por paso, sino en breve tendrá su imagen restaurada." +
                    "\nPuede proceder a guardar la imagen restaurada en Archivo/Guardar.");

        bimg_anterior = bimg_actual;
        actualizarLAnterior ();

        //Pasos del algoritmo de detección
        Paso1 p11 = new Paso1();
        Paso2 p12 = new Paso2();
        Paso3 p13 = new Paso3();
        Paso4 p14 = new Paso4();

        //Aplicar los pasos
        bimg_actual = p11.aplica_paso1(bimg_actual);
        bimg_actual = p12.aplica_paso2(bimg_actual);
        bimg_actual = p13.aplica_paso3(bimg_actual);
        bimg_actual = p14.aplica_paso4(bimg_actual);
        mascara_BSD = bimg_actual;

        //Pasos del algoritmo de restauracion
        Paso1_BSR p21 = new Paso1_BSR();
        Paso2_BSR p22 = new Paso2_BSR();

        bimg_actual = p21.aplica_paso1(bimg_original);
        bimg_actual = p22.aplica_paso2(bimg_actual, mascara_BSD);

        LActual.setIcon(new ImageIcon(ajustarLActual(bimg_actual)));

        BSD.setEnabled(true);
        Paso11.setEnabled(true);
        TODO.setEnabled(true);
    }//GEN-LAST:event_TODOActionPerformed

    private void saveMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveMenuItemActionPerformed
        JFileChooser guardarImagen = new JFileChooser();

        int returnVal = guardarImagen.showSaveDialog(this.getComponent());
        try {
            File fichero = guardarImagen.getSelectedFile();
            ImageIO.write(bimg_actual, "jpg", fichero);
        } catch (IOException e) {
            System.out.println("Error de escritura");
        }
    }//GEN-LAST:event_saveMenuItemActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton BSD;
    private javax.swing.JButton BSR;
    private javax.swing.JProgressBar BarraProceso;
    private javax.swing.JLabel LActual;
    private javax.swing.JLabel LAnterior;
    private javax.swing.JPanel PActual;
    private javax.swing.JPanel PAnterior;
    private javax.swing.JPanel PBotones;
    private javax.swing.JButton Paso11;
    private javax.swing.JButton Paso12;
    private javax.swing.JButton Paso13;
    private javax.swing.JButton Paso14;
    private javax.swing.JButton Paso21;
    private javax.swing.JButton Paso22;
    private javax.swing.JButton TODO;
    private javax.swing.JTextArea Texto;
    private javax.swing.JLabel TextoEstado;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JPanel mainPanel;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JMenuItem openMenuItem;
    private javax.swing.JMenuItem saveMenuItem;
    private javax.swing.JLabel statusAnimationLabel;
    private javax.swing.JPanel statusPanel;
    // End of variables declaration//GEN-END:variables

    private final Timer messageTimer;
    private final Timer busyIconTimer;
    private final Icon idleIcon;
    private final Icon[] busyIcons = new Icon[15];
    private int busyIconIndex = 0;

    private JDialog aboutBox;
}
